template <class T>
struct list_node
{
    T _data;
    list_node<T> *_next;
    list_node<T> *_prev;

    list_node(const T &val)
        : _data(val), _next(nullptr), _prev(nullptr)
    {
    }
};

template <class T, class ref, class ptr>
struct list_it
{
    list_node<T> *_node;

    list_it(list_node<T> *node) : _node(node)
    {
    }

    ref operator*()
    {
        return _node->_data;
    }

    ptr operator->()
    {
        return &(operator*());
    }

    // ++it;
    list_it<T, ref, ptr> &operator++()
    {
        _node = _node->_next;
        return *this;
    }

    // it++;
    list_it<T, ref, ptr> operator++(int)
    {
        list_it<T, ref, ptr> tmp(*this);
        _node = _node->_next;
        return tmp;
    }

    list_it<T, ref, ptr> &operator--()
    {
        _node = _node->_prev;
        return *this;
    }

    list_it<T, ref, ptr> operator--(int)
    {
        list_it<T, ref, ptr> tmp(*this);
        _node = _node->_prev;
        return tmp;
    }

    bool operator==(const list_it<T, ref, ptr> &it)
    {
        return it._node == _node;
    }

    bool operator==(const list_it<T, ref, ptr> &it)
    {
        return it._node != _node;
    }
};

template <class T, class ref, class ptr>
struct r_list_it
{
    list_it _it;
    r_list_it(list_it it)
        : _it(it)
    {
    }

    ref operator*(){

        
    }
};